package operation;

import abbot.WaitTimedOutException;
import abbot.finder.BasicFinder;
import abbot.finder.ComponentNotFoundException;
import abbot.finder.Matcher;
import abbot.finder.MultipleComponentsFoundException;
import abbot.finder.matchers.NameMatcher;
import abbot.tester.ComponentTester;
import abbot.util.Condition;
import com.supermap.data.Point2D;
import com.supermap.data.Workspace;
import com.supermap.desktop.core.Application;
import com.supermap.desktop.core.Interface.IFormMap;
import com.supermap.desktop.core.ScaleModel;
import com.supermap.desktop.core.exception.InvalidScaleException;
import com.supermap.desktop.core.properties.CoreProperties;
import com.supermap.mapping.*;
import com.supermap.ui.MapControl;
import robotCross.CrossRobot;
import robotCross.TextMatcher;
import util.Info;

import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import static operation.RibbonOperation.RIBBONOPERATION;

/**
 * Created by caolp on 2017/3/4.
 */
public class MapOperation extends Operation {
	public MapOperation() {
		if (Application.getActiveApplication().getActiveForm() instanceof IFormMap)
			container = ((IFormMap) Application.getActiveApplication().getActiveForm()).getMapControl();
	}

	public MapOperation(Container container) {
		this.container = container;
	}

	/**
	 * 点击指定容器中的控件
	 *
	 * @param container
	 * @param matcher
	 */
	public void clickComponent(Container container, Matcher matcher) {
		Component component = null;
		try {
			component = new BasicFinder().find(container, matcher);
		} catch (ComponentNotFoundException | MultipleComponentsFoundException e) {
			e.printStackTrace();
		}
		Operation.robot.click(component);
		robot.delay(500);
	}

	/**
	 * 选择地图窗口中的对象,传入的参数为点的地理坐标
	 * 适用于鼠标为漫游状态
	 */
	public void selectMapObject(Point2D point2D) {
		if (container != null) {
			ComponentTester tester = new ComponentTester();
			Point point = ((MapControl) container).getMap().mapToPixel(point2D);
			tester.mouseMove(container, point.x, point.y);
			abbot.tester.Robot.delay(500);
			new CrossRobot().clickRightMouse();
			abbot.tester.Robot.delay(500);
			new CrossRobot().clickLeftMouse();
			abbot.tester.Robot.delay(500);
		}
	}

	/**
	 * 在地图窗口点击指定右键菜单项
	 * 适用于鼠标为拾取状态
	 */
	public void clickMapMenuItem(String menuPath) {
		if (container != null) {
			Point2D point2D = ((MapControl) container).getMap().getCenter();
			Point point = ((MapControl) container).getMap().mapToPixel(point2D);
			ComponentTester tester = new ComponentTester();
			tester.mouseMove(container, point.x, point.y);
			abbot.tester.Robot.delay(500);
			new CrossRobot().clickRightMouse();
			abbot.tester.Robot.delay(500);
			tester.actionSelectPopupMenuItem(container, menuPath);
		}
	}

	public void moveToPoint(Point2D point2D) {
		if (container != null) {
			Point point = ((MapControl) container).getMap().mapToPixel(point2D);
			Operation.robot.mouseMove(container, point.x, point.y);
			abbot.tester.Robot.delay(1000);
		}
	}

	public void clickPoint(Point2D point2D) {
		if (container != null) {
			Point point = ((MapControl) container).getMap().mapToPixel(point2D);
			Operation.robot.click(container, point.x, point.y);
			abbot.tester.Robot.delay(1000);
		}
	}

	public void clickPoints(Point2D[] point2Ds) {
		if (container != null && point2Ds != null) {
			for (Point2D point2D : point2Ds) {
				this.clickPoint(point2D);
			}
		}
	}


	/**
	 * 按住鼠标左键拖拽地图
	 * 适用于鼠标为漫游状态
	 * @param point2D 地理坐标
	 */
	public void dragMouse(Point2D point2D) {
		if (container != null) {
			Point point = ((MapControl) container).getMap().mapToPixel(point2D);
			Operation.robot.drag(container, point.x, point.y);
		}
	}

	/**
	 * 释放鼠标完成地图拖拽
	 *
	 * @param point2D 地理坐标
	 */
	public void dropMouse(Point2D point2D) {
		if (container != null) {
			Point point = ((MapControl) container).getMap().mapToPixel(point2D);
			Operation.robot.drop(container, point.x, point.y);
			abbot.tester.Robot.delay(1000);
		}
	}

	/**
	 * 制作专题图
	 * @param themeType 专题图类型
	 * @param label     专题图类型中的子类
	 */
	public void clickThemeItem(String themeType, String label) throws ComponentNotFoundException, MultipleComponentsFoundException {
		DialogOperation dialogOperation = new DialogOperation("制作专题图");
		dialogOperation.selectListItem(themeType);
		Component[] components = ((JPanel) ((JDialog) dialogOperation.container).getContentPane().getComponents()[0]).getComponents();
		Component[] themeLabels = ((JPanel) components[1]).getComponents();
		for (int j = 0; j < themeLabels.length; j++) {
			if (label.equals(((JLabel) ((JPanel) themeLabels[j]).getComponents()[1]).getText())) {
				clickComponent(((JPanel) themeLabels[j]).getComponents()[1]);
				robot.delay(500);
				break;
			}
		}
		clickComponent(dialogOperation.container, new TextMatcher(CoreProperties.getString("String_Button_OK")));
		robot.delay(3000);
	}

	/**
	 * 选择地图中的对象
	 * @param point2Ds
	 */
	public void selectObjects(Point2D[] point2Ds) throws ComponentNotFoundException, MultipleComponentsFoundException {
		RIBBONOPERATION.clickDropDownButton("地图", "选择", "选择");
		robot.delay(500);
		moveToPoint(point2Ds[0]);
		new CrossRobot().mousePress(InputEvent.BUTTON1_MASK);
		moveToPoint(point2Ds[point2Ds.length-1]);
		new CrossRobot().mouseRelease(InputEvent.BUTTON1_MASK);
		robot.delay(1000);
	}

	/**
	 * 统计专题图：点击添加对话框中指定item项
	 *
	 * @param itemNames item名称
	 */
	public void clickAddDialogItem(String[] itemNames) throws ComponentNotFoundException, MultipleComponentsFoundException {
		DialogOperation dialogOperation = new DialogOperation("添加");
		Component component = dialogOperation.searchComponent(new NameMatcher("ThemeGraphAddItemDialog_listExpressions"));
		if (component != null && component instanceof JList) {
			ListOperation listOperation = new ListOperation((JList) component);
			for (String itemName : itemNames) {
				listOperation.selectItem(itemName);
			}
			dialogOperation.clickComponent(new NameMatcher("ThemeGraphAddItemDialog_buttonSure"));
			Operation.robot.delay(1000);
		}
	}

	/**
	 * 统计专题图：点击添加对话框中指定item项
	 *
	 * @param index item对应的索引号
	 */
	public void clickAddDialogItem(int index) throws ComponentNotFoundException, MultipleComponentsFoundException {
		DialogOperation dialogOperation = new DialogOperation("添加");
		Component component = dialogOperation.searchComponent(new NameMatcher("ThemeGraphAddItemDialog_listExpressions"));
		if (component != null && component instanceof JList) {
			new ListOperation((JList) component).selectIndex(index);
			dialogOperation.clickComponent(new NameMatcher("ThemeGraphAddItemDialog_buttonSure"));
			Operation.robot.delay(1000);
		}
	}

	public void setCenter(Point2D center) {
		setCenter(center, true);
	}

	/**
	 * 设置地图中心点
	 */
	public void setCenter(Point2D center, boolean refresh) {
		if (container != null) {
			MapControl mapControl = (MapControl) container;
			mapControl.getMap().setCenter(center);
			if (refresh) {
				refresh();
			}
		}
	}

	public void setScale(Object scale) {
		setScale(scale, true);
	}

	/**
	 * 设置地图比例尺
	 *
	 * @param refresh 设置结束后是否刷新地图
	 * @param scale
	 */
	public void setScale(Object scale, boolean refresh) {
		if (container != null) {
			MapControl mapControl = (MapControl) container;
			ScaleModel scaleModel = null;
			if (scale instanceof String) {
				try {
					scaleModel = new ScaleModel((String) scale);
				} catch (InvalidScaleException e) {
					e.printStackTrace();
				}
			}
			if (scale instanceof Double) {
				try {
					scaleModel = new ScaleModel((Double) scale);
				} catch (InvalidScaleException e) {
					e.printStackTrace();
				}
			}
			mapControl.getMap().setScale(scaleModel.getScale());
			if (refresh) {
				refresh();
			}
		}
	}

	public void refresh() {
		if (container != null) {
			MapControl mapControl = (MapControl) container;
			mapControl.getMap().refresh();
		}
	}

	/**
	 * 等待地图刷新完成
	 */
	public void waitForDrawn(int timeout) {
		final boolean[] isDrawn = {true};
		if (container != null) {
			MapControl mapControl = (MapControl) container;
			final Map map = mapControl.getMap();
			MapDrawnListener mapDrawnListener = new MapDrawnListener() {
				@Override
				public void mapDrawn(MapDrawnEvent mapDrawnEvent) {
					isDrawn[0] = true;
				}
			};

			MapDrawingListener mapDrawingListener = new MapDrawingListener() {
				@Override
				public void mapDrawing(MapDrawingEvent mapDrawingEvent) {
					isDrawn[0] = false;
				}
			};
			try {
				map.addDrawnListener(mapDrawnListener);
				map.addDrawingListener(mapDrawingListener);
				Condition cond = new Condition() {
					@Override
					public boolean test() {
						return isDrawn[0];
					}
				};
				robot.delay(1000);
				abbot.tester.Robot.wait(cond, timeout);
			} catch (WaitTimedOutException wto) {
				Info.out("地图刷新未完成，等待时间结束。");
			} finally {
				map.removeDrawnListener(mapDrawnListener);
				map.removeDrawingListener(mapDrawingListener);
			}
		}
	}

	/**
	 * 获取当前工作空间中有几个地图
	 *
	 * @return
	 */
	public static int getMapsCount() {
		Workspace workspace = Application.getActiveApplication().getWorkspace();
		return workspace.getMaps().getCount();
	}

	/**
	 * 将地图导出为模板--非UI方式
	 *
	 * @param mapName
	 * @param filePath
	 */
	public static void exportMapTemplate(String mapName, String filePath) {
		Workspace workspace = Application.getActiveApplication().getWorkspace();
		String mapXml = workspace.getMaps().getMapXML(mapName);
		if (mapXml != null && mapXml.length() > 0) {
			File file = new File(filePath);
			File parentFile = file.getParentFile();
			if (!parentFile.exists()) {
				parentFile.mkdirs();
			}
			try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath, true), "UTF-8")) {
				osw.write(mapXml);
				osw.flush();
			} catch (IOException e) {
				Info.out(e.getMessage());
				e.printStackTrace();
			}
		}
	}
}

